﻿using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace Red.Launcher.ViewModels.Workspaces.Database
{
    public class P4Credential : Record
    {
        #region Private Data

        private bool _isDefault;
        private string _password;

        private bool _credentialModified;
        private bool _defaultModified;

        #endregion Private Data

        #region Public Properties

        public static Metadata METADATA { get; private set; }

        public string Password
        {
            get { return _password; }
            set
            {
                if ( _password != value )
                {
                    _password = value;
                    OnPropertyChanged();
                }
            }
        }

        public bool IsDefault
        {
            get { return _isDefault; }
            set
            {
                if ( _isDefault != value )
                {
                    _isDefault = value;
                    OnPropertyChanged();
                }
            }
        }

        public int? DefaultCredentialId { get; private set; }

        #endregion Public Properties

        #region Implemented Properties

        public override Metadata Metadata { get { return METADATA; } }
        public override string Icon { get { return "appbar_key"; } }
        public override IEnumerable<object> Values { get { return new List<object>() { Name, Password }; } }

        #endregion Implemented Properties

        #region C-Tor

        public P4Credential()
        {
            PropertyChanged += P4Credential_PropertyChanged;
        }

        static P4Credential()
        {
            METADATA = new Metadata()
            {
                Table = "P4Credentials",
                Keys = new List<string>() { "username", "password" },
                GenerateSelectSql = GenerateSelectSql,
                CreateDefault = () => { return new P4Credential(); },
                CreateFromDatabaseRow = ( Dictionary<string, object> data ) =>
                {
                    object passwordObj = data[ "password" ];
                    string passwordStr = ( passwordObj.Equals( DBNull.Value ) ) ? "" : (string)passwordObj;

                    object isDefaultObj = data[ "default" ];
                    bool isDefault = ( isDefaultObj.Equals( DBNull.Value ) ) ? false : (bool)isDefaultObj;

                    P4Credential cred = new P4Credential()
                    {
                        Id = (int)data[ "id" ],
                        Name = (string)data[ "username" ],
                        Password = passwordStr,
                        IsDefault = isDefault
                    };

                    object defaultCredentialIdObj = data[ "udc_id" ];
                    if ( !defaultCredentialIdObj.Equals( DBNull.Value ) )
                    {
                        cred.DefaultCredentialId = (int)defaultCredentialIdObj;
                    }

                    return cred;
                }
            };

            METADATA.Children.Add( typeof( P4ClientWorkspace ) );
            METADATA.Joins.Add( typeof( UserDefaultCredential ) );
        }

        #endregion C-Tor

        #region Sql

        private static Sql.Select GenerateSelectSql( Record parent )
        {
            Sql.Select query = METADATA.GenerateSelectSqlStandard( parent );

            Sql.Select.Table udc = Sql.Select.CreateTable( UserDefaultCredential.METADATA.Table, "udc" );
            Sql.Select.Join join = Sql.Select.CreateJoin( udc, Sql.Select.JoinType.Left );

            // Table must match the one created in GenerateSelectSqlStandard()
            Sql.Select.Table querySource = Sql.Select.CreateTable( METADATA.Table, "std" );
            join.Conditions.AddVar( "id", METADATA.ForeignKey, querySource, udc );

            query.Sources.Add( join );
            query.AddColumn( "id", udc, "udc_id" );
            query.AddColumn( "[default]", udc );

            return query;
        }

        protected override void GenerateInsertSql( ref Sql.Transaction transaction, Record parent )
        {
            if( IsDefault && DefaultCredentialId == null )
            {
                UserDefaultCredential udc = new UserDefaultCredential();
                Sql.Insert query = new Sql.Insert( udc );
                query.Parents.Add( this );
                transaction.Add( query );
            }

            base.GenerateInsertSql( ref transaction, parent );
        }

        protected override void GenerateUpdateSql( ref Sql.Transaction transaction, Record parent )
        {
            if( _credentialModified )
            {
                base.GenerateUpdateSql( ref transaction, parent );
            }

            if( _defaultModified )
            {
                if( IsDefault && DefaultCredentialId == null )
                {
                    UserDefaultCredential udc = new UserDefaultCredential();

                    Sql.Insert query = new Sql.Insert( udc );
                    query.Parents.Add( this );
                    transaction.Add( query );
                }
                else if ( !IsDefault && DefaultCredentialId != null )
                {
                    UserDefaultCredential udc = new UserDefaultCredential()
                    {
                        Id = DefaultCredentialId.Value,
                    };

                    Sql.Delete query = new Sql.Delete( udc );
                    transaction.Add( query );
                }
            }
        }

        protected override void GenerateDeleteSql( ref Sql.Transaction transaction, Record parent )
        {
            if( IsDefault )
            {
                UserDefaultCredential udc = new UserDefaultCredential()
                {
                    Id = DefaultCredentialId.Value,
                };

                Sql.Delete query = new Sql.Delete( udc );
                transaction.Add( query );
            }

            base.GenerateDeleteSql( ref transaction, parent );
        }

        #endregion Sql

        #region Event Handlers

        private void P4Credential_PropertyChanged( object sender, PropertyChangedEventArgs e )
        {
            if ( IsWatchingForChanges )
            {
                switch ( e.PropertyName )
                {
                    case "IsDefault":
                        _defaultModified = true;
                        break;

                    case "Name":
                    case "Password":
                        _credentialModified = true;
                        break;
                }
            }
        }

        #endregion Event Handlers
    }
}
